import { Map } from 'ol';
import WebGLVectorLayer from 'ol/layer/WebGLVector';
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import { fromLonLat } from 'ol/proj';
import type { FlatStyleLike } from 'ol/style/flat';
import type { Options } from 'ol/layer/WebGLVector';

/**
 * 点的形状类型
 * circle: 圆形
 * square: 正方形
 * triangle: 三角形
 * star: 五角星
 */
export type PointStyleType = 'circle' | 'square' | 'triangle' | 'star';

/**
 * 点样式配置接口
 * @property {PointStyleType} type - 点的形状类型
 * @property {number} size - 点的大小（像素）
 * @property {string} [color] - 填充颜色（CSS颜色值）
 * @property {number} [strokeWidth] - 边框宽度（像素）
 * @property {string} [strokeColor] - 边框颜色（CSS颜色值）
 */
export interface PointStyleOptions {
  type: PointStyleType;
  size: number;
  color?: string;
  strokeWidth?: number;
  strokeColor?: string;
}

/**
 * 点数据接口
 * @property {number|string} id - 点的唯一标识符
 * @property {number} lon - 经度
 * @property {number} lat - 纬度
 * @property {string} [type] - 点的类型（可选）
 * @property {Record<string, any>} [properties] - 额外的属性（可选）
 */
export interface PointData {
  id: number | string;
  lon: number;
  lat: number;
  type?: string;
  properties?: Record<string, any>;
}

/**
 * 海量点渲染管理器
 * 使用 WebGL 技术实现高性能点图层渲染
 * 支持不同形状、颜色的点的渲染
 * 针对大数据量（50万个点）场景进行了性能优化
 */
export class MassPoints {
  private layer: WebGLVectorLayer;                    // WebGL 图层
  private source: VectorSource;                       // 数据源
  private features: Feature<Point>[] = [];            // 点要素数组
  private map: Map;                                   // 地图实例
  private currentStyle: PointStyleOptions;            // 当前样式配置
  private transformFn = fromLonLat;                   // 坐标转换函数

  /**
   * 构造函数
   * @param {Map} map - OpenLayers地图实例
   * @param {PointData[]} points - 点数据数组
   * @param {PointStyleOptions} style - 样式配置
   */
  constructor(map: Map, points: PointData[], style: PointStyleOptions) {
    this.map = map;
    this.currentStyle = style;
    
    // 创建数据源，禁用水平环绕以提高性能
    this.source = new VectorSource({
      wrapX: false
    });
    
    // 创建 WebGL 图层，配置性能优化选项
    const options: Options = {
      source: this.source,
      style: this.createWebGLStyle(style),
      disableHitDetection: true         // 禁用点击检测以提高性能
    };

    this.layer = new WebGLVectorLayer(options);

    // 批量添加要素
    this.updatePoints(points);

    // 将图层添加到地图
    map.addLayer(this.layer);
  }

  /**
   * 创建点要素
   * 使用对象池和内存复用优化性能
   * @param {PointData[]} points - 点数据数组
   * @returns {Feature<Point>[]} 点要素数组
   */
  private createFeatures(points: PointData[]): Feature<Point>[] {
    const features: Feature<Point>[] = [];
    const transform = this.transformFn;
    const coords = [0, 0];

    // 批量创建要素
    for (let i = 0; i < points.length; i++) {
      const data = points[i];
      // 复用坐标数组，避免创建新数组
      coords[0] = data.lon;
      coords[1] = data.lat;
      const transformed = transform(coords);

      // 创建新的 Point 和 Feature
      const point = new Point(transformed);
      const feature = new Feature({
        geometry: point,
        id: data.id
      });

      features.push(feature);
    }

    return features;
  }

  /**
   * 创建 WebGL 样式
   * 针对不同形状类型生成对应的样式配置
   * @param {PointStyleOptions} options - 样式配置
   * @returns {FlatStyleLike} WebGL样式配置
   */
  private createWebGLStyle(options: PointStyleOptions): FlatStyleLike {
    // 基础样式配置
    const style = {
      'circle-radius': options.size,
      'circle-fill-color': options.color || 'rgba(0,234,255,0.8)',
      'circle-stroke-width': 0                       // 移除描边以提高性能
    } as any;

    // 根据形状类型添加特定样式
    switch (options.type) {
      case 'square':
        style['circle-points'] = 4;                  // 四边形
        style['circle-rotation'] = Math.PI / 4;      // 旋转45度
        break;
      case 'triangle':
        style['circle-points'] = 3;                  // 三角形
        break;
      case 'star':
        style['circle-points'] = 5;                  // 五角星
        style['circle-radius2'] = options.size * 0.5; // 内部半径
        break;
    }

    return style;
  }

  /**
   * 应用样式到图层
   * @param {PointStyleOptions} options - 新的样式配置
   */
  public applyStyle(options: PointStyleOptions): void {
    this.currentStyle = options;
    this.layer.setStyle(this.createWebGLStyle(options));
  }

  /**
   * 更新点数据
   * 使用分批处理和requestAnimationFrame优化大数据量更新
   * @param {PointData[]} points - 新的点数据数组
   */
  public updatePoints(points: PointData[]): void {
    // 清除现有要素
    if (this.source) {
      this.source.clear();
    }

    // 分批处理大量数据
    const batchSize = 10000;                      // 每批处理的数据量
    const totalPoints = points.length;
    let processedPoints = 0;

    const processBatch = () => {
      const end = Math.min(processedPoints + batchSize, totalPoints);
      const batch = points.slice(processedPoints, end);
      
      // 创建并添加要素
      const batchFeatures = this.createFeatures(batch);
      this.source.addFeatures(batchFeatures);
      
      processedPoints = end;
      
      // 如果还有未处理的数据，继续下一批
      if (processedPoints < totalPoints) {
        requestAnimationFrame(processBatch);
      }
    };

    // 开始处理第一批
    requestAnimationFrame(processBatch);
  }

  /**
   * 更新样式配置
   * @param {Partial<PointStyleOptions>} options - 部分样式配置
   */
  public updateStyle(options: Partial<PointStyleOptions>): void {
    this.applyStyle({ ...this.currentStyle, ...options });
  }

  /**
   * 获取图层实例
   * @returns {WebGLVectorLayer} WebGL图层实例
   */
  public getLayer(): WebGLVectorLayer {
    return this.layer;
  }

  /**
   * 获取所有要素
   * @returns {Feature<Point>[]} 点要素数组
   */
  public getFeatures(): Feature<Point>[] {
    return this.features;
  }

  /**
   * 显示图层
   */
  public show(): void {
    this.layer.setVisible(true);
  }

  /**
   * 隐藏图层
   */
  public hide(): void {
    this.layer.setVisible(false);
  }

  /**
   * 销毁图层
   * 清理所有资源
   */
  public destroy(): void {
    if (this.map) {
      this.map.removeLayer(this.layer);
    }
    this.features = [];
    this.source.clear();
  }
} 